package com.king.base;

import com.google.common.base.Objects;

/**
 * @author taomk
 * @version 1.0
 * @since 15-1-31 下午4:32
 */
public class ObjectTest {

	public static void main(String [] args) {
		testEquals();
		testHashCode();
		testToString();
		testCompare();
	}

	/**
	 * equals方法是一个经常需要覆写的方法， 可以查看Object的equals方法注释， 对equals有几个性质的要求：
	 * 1. 自反性reflexive：任何非空引用x，x.equals(x)返回为true；
	 * 2. 对称性symmetric：任何非空引用x和y，x.equals(y)返回true当且仅当y.equals(x)返回true；
	 * 3. 传递性transitive：任何非空引用x和y，如果x.equals(y)返回true，并且y.equals(z)返回true，那么x.equals(z)返回true；
	 * 4. 一致性consistent：两个非空引用x和y，x.equals(y)的多次调用应该保持一致的结果，（前提条件是在多次比较之间没有修改x和y用于比较的相关信息）；
	 * 5. 对于所有非null的值x， x.equals(null)都要返回false。 (如果你要用null.equals(x)也可以，会报NullPointerException);
	 */
	public static void testEquals() {
		System.out.println(Objects.equal("a", "a"));
		System.out.println(Objects.equal(null, "a"));
		System.out.println(Objects.equal("a", null));
		System.out.println(Objects.equal(null, null));

		System.out.println(Objects.equal(new Person("taobangren",23), new Person("taobangren",23)));
		Person person= new Person("taobangren",23);
		System.out.println(Objects.equal(person,person));
	}

	/**
	 * hashCode方法：当覆写（override）了equals()方法之后，必须也覆写hashCode()方法，反之亦然。这个方法返回一个整型值（hash code value），如果两个对象被equals()方法判断为相等，那么它们就应该拥有同样的hash code。Object类的hashCode()方法为不同的对象返回不同的值，Object类的hashCode值表示的是对象的地址。
	 * hashCode的一般性契约（需要满足的条件）如下：
	 * 1.在Java应用的一次执行过程中，如果对象用于equals比较的信息没有被修改，那么同一个对象多次调用hashCode()方法应该返回同一个整型值。应用的多次执行中，这个值不需要保持一致，即每次执行都是保持着各自不同的值。
	 * 2.如果equals()判断两个对象相等，那么它们的hashCode()方法应该返回同样的值。
	 * 3.并没有强制要求如果equals()判断两个对象不相等，那么它们的hashCode()方法就应该返回不同的值。即，两个对象用equals()方法比较返回false，它们的hashCode可以相同也可以不同。但是，应该意识到，为两个不相等的对象产生两个不同的hashCode可以改善哈希表的性能。
	 */
	public static void testHashCode() {
		System.out.println(Objects.hashCode("a"));
		System.out.println(Objects.hashCode("a"));
		System.out.println(Objects.hashCode("a","b"));
		System.out.println(Objects.hashCode("b","a"));
		System.out.println(Objects.hashCode("a","b","c"));

		Person person=new Person("taobangren",23);
		System.out.println(Objects.hashCode(person));
		System.out.println(Objects.hashCode(person));
	}

	/**
	 * toString()方法：因为每个类都直接或间接地继承自Object，因此每个类都有toString()方法。这个方法是用得最多的, 覆写得最多, 一个好的toString方法对于调试来说是非常重要的, 但是写起来确实很不爽。
	 */
	public static void testToString() {
		System.out.println(Objects.toStringHelper(ObjectTest.class).add("x", 1).toString());
		System.out.println(Objects.toStringHelper(Person.class).add("x", 1).toString());

		Person person=new Person("taobangren",23);
		String result = Objects.toStringHelper(Person.class).add("name", person.name).add("age", person.age).toString();
		System.out.print(result);
	}

	/**
	 * compareTo：compareTo(Object o)方法是java.lang.Comparable<T>接口中的方法，当需要对某个类的对象进行排序时，该类需要实现 Comparable<T>接口的，必须重写public int compareTo(T o)方法。java规定，若a，b是两个对象，当a.compareTo(b)>0时，则a大于b，a.compareTo(b)<0时，a<b，即规定对象的比较大小的规则；
	 * compare： compare(Object o1,Object o2)方法是java.util.Comparator<T>接口的方法，compare方法内主要靠定义的compareTo规定的对象大小关系规则来确定对象的大小；
	 * compareTo方法的通用约定与equals类似：将本对象与指定的对象停止比拟，如果本对象小于、等于、或大于指定对象，则分离返回正数、零、或正数。如果指定的对象类型无法与本对象停止比拟，则跑出ClassCastException。
	 * 对称性：实现者必须保证对全部的x和y都有sgn(x.compareTo(y)) == -sgn(y.compareTo(x))。这也暗示当且仅当y.compareTo(x)抛出异常时，x.compareTo(y)才抛出异常。
	 * 传递性：实现者必须保证比拟关系是可传递的，如果x.compareTo(y) > 0且y.compareTo(z) > 0，则x.compareTo(z) > 0。实现者必须保证x.compareTo(y)==0暗示着全部的z都有(x.compareTo(z)) == (y.compareTo(z))。
	 * 虽不强制要求，但强烈建议(x.compareTo(y) == 0) == (x.equals(y))。一般来说，任何实现了Comparable的类如果违背了这个约定，都应该明白说明。推荐这么说：“注意：本类拥有自然顺序，但与equals不一致”。
	 */
	public static void testCompare() {
		Student student=new Student("peida",23,80);
		Student student1=new Student("aida",23,36);
		Student student2=new Student("jerry",24,90);
		Student student3=new Student("peida",23,80);

		System.out.println("==========equals===========");
		System.out.println(Objects.equal(student, student1));
		System.out.println(Objects.equal(student1, student2));
		System.out.println(Objects.equal(student, student3));

		System.out.println("==========hashCode===========");
		System.out.println(Objects.hashCode(student));
		System.out.println(Objects.hashCode(student1));
		System.out.println(Objects.hashCode(student2));
		System.out.println(Objects.hashCode(student3));

		System.out.println("==========toString===========");
		System.out.println(Objects.toStringHelper(Student.class).add("name", student.name).toString());
		System.out.println(student1.toString());
		System.out.println(student2.toString());
		System.out.println(student3.toString());

		System.out.println("==========compareTo===========");
		System.out.println(student.compareTo(student1));
		System.out.println(student.compareTo(student2));
		System.out.println(student2.compareTo(student1));
		System.out.println(student2.compareTo(student));
		System.out.println(new StudentComparator().compare(student1, student2));
		System.out.println(new StudentComparator().compare(student, student3));
	}
}
